<template>
 <el-popover
    v-model="isShow"
    ref="myPopover"
    popper-class="tree-select-popover"
    placement="bottom-start"
    transition="el-zoom-in-top"
    trigger="click">
    <el-input  slot="reference" :style="{ width: width + 'px' }" 
    :placeholder="placeholder" ref="input" readonly  :clearable="clearable"
    @mouseover.native="mouseover"  @mouseout.native="mouseout"
    style="cursor:pointer" v-model="text">
        <i slot="suffix" class="el-select__caret el-input__icon el-icon-circle-close" v-if="showClearable" @click.stop="clear"></i>
        <i slot="suffix" class="el-select__caret el-input__icon el-icon-arrow-up"  v-else  
        :class="{ 'is-reverse' : isShow}"></i>
    </el-input>
    <el-scrollbar style="height: 250px;" :native="false">  
        <div style="padding: 0px 10px;margin: 5px 0px 0px;">
          <el-input  placeholder="输入关键字进行过滤" prefix-icon="el-icon-search" v-model="filterText" size="mini"></el-input>
        </div>
        <el-tree
          class="filter-tree"
          :data="data"
          :node-key="defaultProps.id"
          @node-click="nodeClick"
          @check="check"
            default-expand-all
          :default-expanded-keys="defaultExpandedKeys"
          :props="defaultProps"
          :accordion="accordion"
          :show-checkbox="showCheckbox"
          :filter-node-method="filterNode"
          ref="tree">
        </el-tree>
    </el-scrollbar>     
</el-popover>
</template>
<script>
export default {
  name: 'TreeSelect',
  props: {
    clearable: {
      type: Boolean,
      default: false
    },
    placeholder: {
      type: String,
      default: 'placeholder'
    },
    textFormatter: Function,
    // 是否只有叶子节点可以选中
    isLeafClick: {
      type: Boolean,
      default: false
    },
    width: {
      type: Number,
      default: 220
    },
    showCheckbox: { // 是否多选
      type: Boolean,
      default: false
    },
    accordion: { // 是否每次只展开一层
      type: Boolean,
      default: false
    },
    defaultProps: {
      type: Object,
      default: () => {
        return {
          id: 'id',
          children: 'children',
          label: 'label'
        };
      }
    },
    data: {
      type: Array,
      default: () => []
    },
    checkedKeys: Array // 默认选中

  },
  watch: {
    filterText(val) {
      this.$refs.tree.filter(val);
    },
    checkedKeysAndDataLoad: {
      handler(val) {
        const { checkedKeys, data } = val;
        this.$nextTick(_ => {
          if (checkedKeys) {
            if (!checkedKeys.length) {
              this.checkedNodes = [];
              if (this.showCheckbox) {
                this.$refs.tree.setCheckedKeys([]);
              } else {
                this.$refs.tree.setCurrentKey(null);
              }
            }
            if (checkedKeys && data) {
              if (checkedKeys.length && data.length) {
                this.setCheckedKeys(this.checkedKeys);
              }
            }
          }
        });
      },
      immediate: true
    }
  },
  computed: {
    text() {
      if (this.textFormatter) {
        const value = this.showCheckbox ? this.checkedNodes : this.checkedNodes[0];
        return this.checkedNodes.length
          ? this.textFormatter(value)
          : '';
      } else {
        return this.checkedNodes.length
          ? this.checkedNodes.map(v => v[this.defaultProps.label]).toString()
          : '';
      }
    },
    checkedKeysAndDataLoad() {
      const { checkedKeys, data } = this;
      return {
        checkedKeys,
        data
      };
    }
  },
  methods: {
    mouseover() {
      if (this.clearable && this.text) {
        this.showClearable = true;
      } else {
        this.showClearable = false;
      }
    },
    mouseout() {
      this.showClearable = false;
    },
    resert() {
      this.checkedNodes = [];
      // 多选
      if (this.showCheckbox) {
        this.$refs.tree.setCheckedKeys([]);
      } else {
        this.$refs.tree.setCurrentKey(null);
      }
    },
    clear() {
      this.checkedNodes = [];
      if (this.showCheckbox) {
        this.$refs.tree.setCheckedKeys([]);
        this.$emit('change', []);
      } else {
        this.$refs.tree.setCurrentKey(null);
        this.$emit('change', {});
      }
    },
    // 设置选中
    setCheckedKeys(checkedKeys) {
      if (this.showCheckbox) { // 多选
        this.$refs.tree.setCheckedKeys([]);
        this.$refs.tree.setCheckedKeys(checkedKeys);
        this.checkedNodes = this.$refs.tree.getCheckedNodes();
        this.$emit('change', this.checkedNodes);
      } else { // 单选
        this.$refs.tree.setCurrentKey(checkedKeys[0]);
        this.defaultExpandedKeys = [checkedKeys[0]];
        const currentNode = this.$refs.tree.getCurrentNode();
        this.checkedNodes = [currentNode];
        this.$emit('change', currentNode);
      }
    },
    // 单选
    nodeClick(a, b, c) {
      if (this.showCheckbox === false) {
        if (this.isLeafClick) {
          if (b.isLeaf) { // 叶子节点
            this.checkedNodes = [b.data];
            this.isShow = false;
            this.$emit('change', b.data);
          }
        } else {
          this.checkedNodes = [b.data];
          this.isShow = false;
          this.$emit('change', b.data);
        }
      }
    },
    // 多选
    check(a, b) {
      if (this.showCheckbox === true) {
        this.checkedNodes = b.checkedNodes;
        this.$emit('change', this.checkedNodes);
      }
    },
    filterNode(value, data) {
      if (!value) return true;
      const key = this.defaultProps.label;
      return data[key].indexOf(value) !== -1;
    }
  },
  data() {
    return {
      showClearable: false,
      isShow: false,
      checkedNodes: [],
      filterText: '',
      defaultExpandedKeys: []
    };
  },
  created() {

  }
};
</script>
<style lang="scss">
.tree-select-popover{
  padding: 0;
  .popper__arrow{
     left: 35px !important;
  }
}
</style>

<style lang="scss" scoped>
   .el-select__caret {
      color: #c0c4cc;
      font-size: 14px;
      transition: transform .3s;
      transform: rotate(180deg);
      cursor: pointer;
    }
    .el-select__caret.is-reverse {
      transform: rotate(0deg);
    }
   
</style>
